The WinAPI Wrapper Library is my C++ class library, that is a wrapper for the Windows API. I have been writing it for a longer period of time, cleaning it and adding new classes. Recently, I've decided to release it to the public. The library is available for free only if you are going to create free software with it.
The main design goals of the library follow:
The Win32 API is a C API, but many functions are permanently bound to objects, and typically the objects they refer to come as the first argument. Such objects can be naturally wrapped up with C++ classes.
All wrapper classes are lightweight and fully transparent, and do not introduce any overhead. Simply because they don't have virtual members nor any extra fields and all their member functions are inline.
Creating your own windows in C-oriented Win32 API can be very clumsy, especially for a C++ application. The library contains classes to inherit from, that replace the WNDPROC callback, that simplify and enhance the process of creating new window types. The so-called WNDCLASS is also a secondary notion now, and can be seamlessly and transparently entangled into program code.
Many, many functions in the Win32 API are... ugly! The Win32 API is a terrible example of how not to design software interfaces. This is actually not a fault of Microsoft - they just wanted it to be backward compatible. Still, many functions have lots of arguments, most of which are usually set to typical values, or are dwReserved. Member functions of the wrapper classes in my library have many of these arguments reordered and most of the arguments have their default values - so that you don't have to type all arguments and you only enter the arguments you really need. The last arguments are usually the most rarely used.
Creating a simple or a complex application in Win32 API always requires having some code. In this article, I will prove that in the WinAPI Wrapper Library this need has been reduced to minimum. You can skip all the typical code and write only the code that actually does something specific for your application. Still, everything has as minimal overhead as possible.
You can use the WinAPI Wrapper Library entirely or partially. You can for example use only parts of it of your choice, and skip the rest. You can mix code that uses the library with typical Win32 API code, or even with MFC code.
The library also contains several other helper classes, like for example the latest addition - a template class, a smart interface pointer for COM interfaces (it's actually a little bit smarter than the ATL equivalent ;-) ).
Let's cut to the chase.
A simple application
The following code shows a basic "Hello, World!" application written using the WinAPI Wrapper Library.
#include <winapi.h>
using namespace WinAPI;
class MainWindow: public Window {
public:
MainWindow() {
Create( "Hello, World!" );
}
protected:
virtual void OnDestroy() {
PostQuitMessage( 0 );
}
virtual void OnPaint() {
PaintDC dc( *this );
dc.TextOut( WPoint(50,50), "Hello, World!" );
}
private:
virtual ~MainWindow() { }
};
namespace {
Application< MainWindow > app;
}
Let's discuss particular lines of the above code. The first line is of course the inclusion of the library header. This header already includes all Windows API stuff - so you don't need to do it even if you use some parts of it without the wrapper.
The second line defines the WinAPI namespace in the global namespace. Everything in the WinAPI Wrapper Library is defined in the WinAPI namespace, so it won't collide with other things in other APIs and libraries or in your code. If you don't have anything colliding, you can simply include the entire WinAPI namespace like it's in the example.
Next, the main window class is defined. This is an enhanced functionality of the library that goes beyond the "wrapper" hype. Instead of creating a WNDPROC function and blending everything in one pot, you just have a nice class and you can use it in many ways, perhaps inheriting from it or doing other things. Still, everything remains clean in the C++ way.
As you can see, the MainWindow class has several functions with different accessibility - public, protected or private. This has its purpose. The constructor must be public, in order for you to be able to create instances of this class - particular windows. The methods are protected, because they are called by the class internals when new messages arive and you don't want them to be called externally, although it still could be possible to override them in derived classes. The destructor is private - from the nature of the Window class - this is described later in this article.
Guess what the particular functions of the MainWindow class do. I bet you got it right! The constructor actually creates the window. The Create() function is an inline wrapper function for the CreateWindowEx() monster from the Win32 API. It's clean as it takes only the window name in the example; however, you can still feed it with all other arguments, because they are there - they only have default values so you don't need to specify them if you don't want to. The OnDestroy() and OnPaint() methods are called in response to WM_DESTROY and WM_PAINT messages. The OnDestroy() method calls PostQuitMessage() from the Win32 API in order to quit the application after the main window dies - this is the regular Windows way of quitting an application. The OnPaint() paints the "Hello, World!" text on the window - it does it using the PaintDC class that automatically allocates and frees the paint DC, so you don't have to remember to call EndPaint(). (This is only for the purpose of the example - the OnPaint() method could have only one line, without defining the dc variable). The last function - the destructor - does nothing, as it is there only to be private, so you can't derive from the MainWindow class.
It's worth to mention that if you call Create() in the constructor, don't derive from the class, because the methods defined in the derived class will not be called, since the class wasn't initialized properly yet (the virtual method table is fully initialized after the top-level constructor exits).
The life span of a Window may seem a little bit weird. There is a class in the library - the GenericWindow class - that wraps functionality of a typical window. You can use it on any HWND objects in order to simplify your code, but this class doesn't free the HWND handle in the destructor - you have to do it explicitly calling GenericWindow::Destroy() or DestroyWindow() from the Win32 API. You typically create instances of GenericWindow statically, either as class members or in your routines. However, the Window class (actually derived from GenericWindow), has in addition some virtual methods and it behaves very differently. You have to create instances of Window-derived classes dynamically with the new operator. You must also never call the delete operator on Window-derived classes. This is because Window objects are automatically freed when their window-counterparts die (typically when handling the last message of a dying window - WM_NCDESTROY).
Knowing all this we can go to the last line of the example. Well, you could now create your typical WinMain() function, do the typical message loop in it and only create your main window the WinAPI Wrapper Library way, like this:
MainWindow* p_mainwnd = new MainWindow;
p_mainwnd->Show();
p_mainwnd->Update();
What's wrong with that? Nothing, actually. It's a entirely correct code. But what for, while you can do all this in one line? ;-) Well, the WinAPI Wrapper Library contains its own WinMain function that is used by the compiler if you don't specify your own WinMain (the trick with WinMainCRTStartup() works perfectly, although you have to forget about the library's WinMain). The library's WinMain assumes that you have created exactly one application object somewhere (anywhere) in your application, e.g. in an anonymous namespace - not accessible from other source files. The application object is an object of a template class Application. The first argument of this template is your main window class - now the application object creates the main window for you using your class, and it performs the message queue. The Application template has also other arguments in which you can specify accelerators processor or your own message queue.
There's another important thing to be aware of. As you have seen above, the Window class has several virtual methods for handling common messages. There are only a few of them (WM_CREATE, WM_MOUSEMOVE, WM_COMMAND, etc.) - the rest of messages goes to the HandleMessage() method. You can follow this functionality and write your own OnXXX() handlers and call them from your overriden HandleMessage(). Another way is to handle ALL messages in HandleMessage() (when you #define PURE_WRAPPER before #including <winapi.h>, the only method in the Window class is HandleMessage() and none of the others are defined). Yet another way is to create your own message maps (if you like the MFC way), and handle them in HandleMessage(), either way (with or withour PURE_WRAPPER). You are free to decide.
There are also other classes similar to Window. These include: Dialog, ModelessDialog, MDIFrameWindow and MDIChildWindow.
What's more there for you?
The WinAPI Wrapper Library has several other facilities and wrappers, including:
Handling files. The File class provides much of a simplification to the good old file handling routines in the Win32 API.
Searching for files. You can use the FindFile class that wraps the find handle, or just call one of its static members to get the list of all specified files at once.
File open/save and folder dialogs from the common dialogs library. It's never been easier to ask the user to open a file.
Miscellaneous controls, also from the common controls library. Now creating and using standard controls is easier.
BSD-networking has Socket and Address wrapper classes that simplify writing socket-based networking applications.
GDI wrapper classes for DCs and GDI objects. Also includes the SelectObj class that automatically deselects objects from a DC, so you don't have to worry about GDI resource leaks anymore.
Simplified multithreading. Now a thread is a class, and the Thread::Run() method replaces the ThreadProc function. If you take advantage of the C++'s multiple derivation, you can for example create a window that has its own thread (e.g. deriving both from Window and Thread). This for example simplifies making progress bars, etc.
The aforementioned smart interface pointer class is at hand when you want a clean COM code.
Installation notes
You can download the WinAPI Wrapper Library from http://winapi.chris.dragan.name/. The package you download is an MSI installer. I'm sorry in advance for the large size - my own installer was almost 3 times smaller, but it was incapable of a good integration of the help into Visual Studio.
The package contains the header and four libs (for four different versions of the library). The package also contains several goodies for the users of Microsoft Visual Studio .NET, such as sample apps, help integrated into the environment, an AppWizard with several application options for beginner developers and it instals the paths to the library in the environment. If you use VS6 or VC++ .NET, you will have to either set up the paths to the header and libs in the environment, or copy the header and the libs to the compilers folders.
Final words
I know it's not perfect, but if you create an application that has only a few API calls, you will probably want to make it look simplier. On the other hand the library is great with complex applications, as it saves you much work, while the compiler still delivers machine code with the same quality as if you used plain Win32 API.
All programmers who use my library have mentioned that it's better than MFC, because it's much simpler and lightweight. Of course an MFC application can be as small as 9KB, when you link it to the MSVCRT.DLL, but you can achieve the same thing when using the WinAPI Wrapper Library.